// -*- mode:c++ -*-

// Copyright (c) 2020 Metempsy Technology Consulting
// All rights reserved
//
// The license below extends only to copyright in the software and shall
// not be construed as granting a license to any other intellectual
// property including but not limited to intellectual property relating
// to a hardware implementation of the functionality of the software
// licensed hereunder.  You may use the software subject to the license
// terms below provided that you ensure that this notice is replicated
// unmodified and in its entirety in all distributions of the software,
// modified or unmodified, in source code or in binary form.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met: redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer;
// redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution;
// neither the name of the copyright holders nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

let {{

    header_output = ""
    decoder_output = ""
    exec_output = ""


    def buildPauthObject(mnem, templateBase, opcode, optArgs=[]):
        global header_output, decoder_output, exec_output
        pac_code = '''//uint64_t val = 0;
                uint64_t res;
                fault = %(op)s(xc->tcBase(), %(op1)s, %(op2)s, &res);
                XDest = res;
                '''
        if templateBase=='DataX2Reg':
            code = pac_code % {"op1": 'Op164',
                               "op2": 'Op264',
                               "op":  opcode }
        else:
            code = pac_code % {"op1": 'XDest',
                               "op2": 'Op164',
                               "op":  opcode }

        iop = InstObjParams(mnem, mnem, templateBase+"Op", code, optArgs)
        header_output += eval(templateBase + "Declare").subst(iop)
        decoder_output += eval(templateBase + "Constructor").subst(iop)
        exec_output += BasicExecute.subst(iop)

    def buildXPauthObject(mnem, optArgs=[]):
        global header_output, decoder_output, exec_output
        templateBase = "XPauthOpRegReg"

        code =  'uint64_t res;\n'\
                'fault = stripPAC(xc->tcBase(), XDest, data, &res);\n'
        code += 'XDest = res;'
        regoptype = 'RegOp'

        iop = InstObjParams(mnem, mnem, regoptype, code, optArgs)
        header_output += eval(templateBase + "Declare").subst(iop)
        decoder_output += eval(templateBase + "Constructor").subst(iop)
        exec_output += BasicExecute.subst(iop)


    buildPauthObject("Pacda",  "DataX1Reg", 'addPACDA')
    buildPauthObject("Pacdza", "DataX1Reg", 'addPACDA')
    buildPauthObject("Pacdb",  "DataX1Reg", 'addPACDB')
    buildPauthObject("Pacdzb", "DataX1Reg", 'addPACDB')
    buildPauthObject("Pacga",  "DataX2Reg", 'addPACGA')

    buildPauthObject("Pacia",     "DataX1Reg", 'addPACIA')
    buildPauthObject("Pacia1716", "DataX1Reg", 'addPACIA')
    buildPauthObject("Paciasp",   "DataX1Reg", 'addPACIA')
    buildPauthObject("Paciaz",    "DataX1Reg", 'addPACIA')
    buildPauthObject("Paciza",    "DataX1Reg", 'addPACIA')

    buildPauthObject("Pacib",     "DataX1Reg", 'addPACIB')
    buildPauthObject("Pacib1716", "DataX1Reg", 'addPACIB')
    buildPauthObject("Pacibsp",   "DataX1Reg", 'addPACIB')
    buildPauthObject("Pacibz",    "DataX1Reg", 'addPACIB')
    buildPauthObject("Pacizb",    "DataX1Reg", 'addPACIB')

    buildPauthObject("Autda",     "DataX1Reg", 'authDA')
    buildPauthObject("Autdza",    "DataX1Reg", 'authDA')
    buildPauthObject("Autdb",     "DataX1Reg", 'authDB')
    buildPauthObject("Autdzb",    "DataX1Reg", 'authDB')

    buildPauthObject("Autia",     "DataX1Reg", 'authIA')
    buildPauthObject("Autia1716", "DataX1Reg", 'authIA')
    buildPauthObject("Autiasp",   "DataX1Reg", 'authIA')
    buildPauthObject("Autiaz",    "DataX1Reg", 'authIA')
    buildPauthObject("Autiza",    "DataX1Reg", 'authIA')

    buildPauthObject("Autib",     "DataX1Reg", 'authIB')
    buildPauthObject("Autib1716", "DataX1Reg", 'authIB')
    buildPauthObject("Autibsp",   "DataX1Reg", 'authIB')
    buildPauthObject("Autibz",    "DataX1Reg", 'authIB')
    buildPauthObject("Autizb",    "DataX1Reg", 'authIB')

    buildXPauthObject("Xpacd")
    buildXPauthObject("Xpaci")
    buildXPauthObject("Xpaclri")
}};
